﻿#include "musicwidget.h"
#include <QStandardPaths>
#include <QScrollBar>

MusicWidget::MusicWidget(QWidget *parent):
    QWidget(parent)
{
    this->isPlay = false;
    this->isExist = false;
    this->addButton = new QPushButton("添加音乐");
    this->removeButton = new QPushButton("删除音乐");
    QHBoxLayout *hlayout1 = new QHBoxLayout;
    hlayout1->addWidget(addButton);
    hlayout1->addWidget(removeButton);

    this->songListWidget = new QListWidget;
    QVBoxLayout *vlayout1 = new QVBoxLayout;
    vlayout1->addLayout(hlayout1);
    vlayout1->addWidget(this->songListWidget);

    this->lyricsEdit = new QTextEdit;
    QHBoxLayout *hlayout2 = new QHBoxLayout;
    hlayout2->addLayout(vlayout1);
    hlayout2->addWidget(this->lyricsEdit);

    this->timeLabel = new QLabel(mDurationTime+"/"+mPositionTime);
    this->timeSlider = new QSlider;
    timeSlider->setOrientation(Qt::Horizontal);
    this->soundLabel = new QLabel;
    soundLabel->setPixmap(QPixmap(":/images/sound2.png"));
    this->soundSizeLabel = new QLabel("50%");
    this->soundSlider = new QSlider;
    soundSlider->setOrientation(Qt::Horizontal);
    QHBoxLayout *hlayout3 = new QHBoxLayout;
    hlayout3->addWidget(timeLabel);
    hlayout3->addWidget(timeSlider);
    hlayout3->addWidget(soundLabel);
    hlayout3->addWidget(soundSizeLabel);
    hlayout3->addWidget(soundSlider);

    this->prevButton = new QPushButton;
    prevButton->setIcon(QIcon(":/images/bfzn_001.png"));
    prevButton->setIconSize(QSize(100,100));
    this->playButton = new QPushButton;
    playButton->setIcon(QIcon(":/images/bfzn_004.png"));
    playButton->setIconSize(QSize(100,100));
    this->nextButton = new QPushButton;
    nextButton->setIcon(QIcon(":/images/bfzn_002.png"));
    nextButton->setIconSize(QSize(100,100));
    QHBoxLayout *hlayout4 = new QHBoxLayout;
    hlayout4->addStretch();
    hlayout4->addWidget(prevButton);
    hlayout4->addStretch();
    hlayout4->addWidget(playButton);
    hlayout4->addStretch();
    hlayout4->addWidget(nextButton );
    hlayout4->addStretch();

    QVBoxLayout *mainlayout = new QVBoxLayout(this);
    mainlayout->addLayout(hlayout2);
    mainlayout->addLayout(hlayout3);
    mainlayout->addLayout(hlayout4);

    initMusicWidget();
    connect(addButton, &QPushButton::clicked, this, &MusicWidget::slot_addMusic);
    connect(removeButton, &QPushButton::clicked, this, &MusicWidget::slot_removeMusic);
    connect(playButton, &QPushButton::clicked, this, &MusicWidget::slot_playMusic);
    connect(prevButton, &QPushButton::clicked, this, &MusicWidget::slot_prevMusic);
    connect(nextButton, &QPushButton::clicked, this, &MusicWidget::slot_nextMusic);

    // 音量滑块连接
    connect(soundSlider, &QSlider::valueChanged, this, &MusicWidget::slot_changeSound);

    // 进度条连接
    connect(timeSlider, &QSlider::sliderMoved, this, [this](int value) {
        mPlayer->setPosition(value);
    });
    connect(songListWidget, &QListWidget::itemDoubleClicked,
            this, &MusicWidget::slot_itemDoubleClicked);
}

void MusicWidget::scrollLyricsToCenter(int line)
{
    if (line < 0) return;

    // 计算要滚动到的位置
    int scrollPos = line * lyricsEdit->fontMetrics().height();
    // 调整到中间位置
    int centerPos = scrollPos - (lyricsEdit->height() / 2);
    // 设置滚动条位置
    lyricsEdit->verticalScrollBar()->setValue(centerPos);
}

void MusicWidget::initMusicWidget()
{
    //    创建播放器对象 QMediaPlayer 给 mPlayer
    this->mPlayer = new QMediaPlayer(this);
    //     创建播放器对象 QMediaPlaylist 给 mPlayList
    this->mPlayList = new QMediaPlaylist(this);
    //     将播放器列表 mPlayList 设置到播放器 mPlayer 中
    this->mPlayer->setPlaylist(mPlayList);
    //     设置播放器列表 mPlayList 的播放模式 Loop:循环播放
    this->mPlayList->setPlaybackMode(QMediaPlaylist::Loop);
    //     设置播放器 mPlayer 的声音大小为 50
    this->mPlayer->setVolume(50);
    //     初始化声音组件 soundSlider 的 setMinimum(0)，setMaximum(100)，
    this->soundSlider->setMinimum(0);
    this->soundSlider->setMaximum(100);
    //    setValue(50)
    this->soundSlider->setValue(50);
    //     mPlayList 的 currentIndexChanged 信号关联 slot_playlistChanged槽函数
    connect(mPlayList,SIGNAL(currentIndexChanged(int)),this,SLOT(slot_playlistChanged(int)));
    //     mPlayer 的 positionChanged 信号关联 slot_positionChanged 槽函数
    connect(mPlayer,SIGNAL(positionChanged(qint64)),this,SLOT(slot_positionChanged(qint64)));
    //     mPlayer 的 durationChanged 信号关联 slot_durationChanged 槽函数
    connect(mPlayer,SIGNAL(durationChanged(qint64)),this,SLOT(slot_durationChanged(qint64)));
    //     初始化 FuTcpServer
    fuTcpServer = FuTcpServer::getTcpServer();
    //     初始化 isPlay 为 false
    this->isPlay = false;
}



void MusicWidget::slot_playlistChanged(int rowNo)
{
    //    根据参数 rowNo 设置 songListWidget 的当前行号
    this->songListWidget->setCurrentRow(rowNo);
    //    调用 loadMusicLrc 函数加载当前音乐歌词
    this->loadMusicLrc(rowNo);
    //    判断 musicSendthread 是否为空，
    if (isPlay) {
        // 停止并清理之前的发送线程
        if(this->musicSendthread != nullptr) {
            if(!this->musicSendthread->isFinished()) {
                this->musicSendthread->setStop(true);
                this->musicSendthread->quit();
                this->musicSendthread->wait();
            }
            delete musicSendthread;
            this->musicSendthread = nullptr;
        }

        // 启动新的发送线程
        QMediaContent media = mPlayList->currentMedia();
        QString filepath = media.canonicalUrl().toLocalFile();
        if(!filepath.isEmpty()) {
            musicSendthread = new MusicSendThread(filepath);
            musicSendthread->start();
        }
    }
}

void MusicWidget::slot_positionChanged(qint64 position)
{
    // 只有在用户没有拖动滑块时才自动更新
    if (!timeSlider->isSliderDown()) {
        this->timeSlider->setSliderPosition(position);

        // 计算时分秒放到 timeLabel
        int secs = position/1000;
        int min = secs/60;
        int sec = secs%60;
        this->mPositionTime = QString::number(min)+":"+QString::number(sec);
        this->timeLabel->setText(mPositionTime+"/"+mDurationTime);

        // 更新歌词
        this->updateLrcOfposition(position);
    }
}

void MusicWidget::slot_durationChanged(qint64 duration)
{
    this->timeSlider->setMaximum(duration);

    // 计算分秒，放入到 timeLabel
    int secs = duration/1000;
    int min = secs/60;
    int sec = secs%60;
    this->mDurationTime = QString::number(min)+":"+QString::number(sec);
    this->timeLabel->setText(mPositionTime+"/"+mDurationTime);
}

void MusicWidget::slot_addMusic()
{
    if (fuTcpServer->socket == nullptr) {
        QMessageBox::critical(this, "错误", "客户端未连接");
        return;
    }
    //用文件对话框对象选择多个音乐文件，然后循环放入 mPlayList、songListWidget
    QStringList fileList = QFileDialog::getOpenFileNames(this,"选择音乐","./","all file(*.*)");

    if (fileList.isEmpty()) {
        return;
    }

    for (const QString &filePath : fileList) {
        QUrl mediaUrl = QUrl::fromLocalFile(filePath);
        mPlayList->addMedia(mediaUrl);

        QFileInfo fileInfo(filePath);
        songListWidget->addItem(fileInfo.fileName());
    }

    if (mPlayList->mediaCount() > 0 && !isExist) {
        // 只设置存在标志，不设置当前索引
        isExist = true;
        // 选中第一首但不触发播放
        songListWidget->setCurrentRow(0);
    }
}

void MusicWidget::slot_removeMusic()
{
    if (fuTcpServer->socket == nullptr)
    {
        QMessageBox::critical(this, "错误", "客户端未连接");
        return;
    }
    int currentRow = songListWidget->currentRow();
    if (currentRow < 0 || currentRow >= songListWidget->count()) {
        return;
    }

    isExist = (mPlayList->mediaCount() > 1);
    // 如果删除的是当前播放的歌曲
    if (currentRow == mPlayList->currentIndex()) {
        if (musicSendthread && musicSendthread->isRunning()) {
            musicSendthread->setStop(true);
            musicSendthread->quit();
            musicSendthread->wait();
            delete musicSendthread;
            musicSendthread = nullptr;
        }

        if (mPlayer->state() == QMediaPlayer::PlayingState) {
            mPlayer->stop();
            isPlay = false;
            playButton->setIcon(QIcon(":/images/bfzn_004.png"));
        }
        // 检查是否还有歌曲
        if(isExist)
        {
            this->mPlayList->next();
        }
    }
    mPlayList->removeMedia(currentRow);
    delete songListWidget->takeItem(currentRow);
    if(!isExist)
    {
        lyricsEdit->clear();
    }
}

void MusicWidget::slot_playMusic()
{
    if (fuTcpServer->socket == nullptr) {
        QMessageBox::critical(this, "错误", "客户端未连接");
        return;
    }

    if (!isExist) {
        QMessageBox::warning(this, "提示", "请先添加音乐");
        return;
    }

    int currentRow = songListWidget->currentRow();
    if (currentRow >= 0 && currentRow != mPlayList->currentIndex()) {
        // 设置播放列表当前索引，但不启动播放
        mPlayList->setCurrentIndex(currentRow);
        // 不调用 mPlayer->stop()，保持当前状态
    }

    QByteArray command;
    if (isPlay) {
        // 暂停播放
        command = QByteArray::number(Common::pauseMusic);

        // 停止发送线程
        if (musicSendthread && musicSendthread->isRunning()) {
            musicSendthread->setStop(true);
            musicSendthread->quit();
            musicSendthread->wait();
        }
    } else {
        // 开始播放
        command = QByteArray::number(Common::playMusic);

        // 确保有当前选中的歌曲
        if (mPlayList->currentIndex() == -1 && mPlayList->mediaCount() > 0) {
            mPlayList->setCurrentIndex(0);
        }

        // 启动发送线程（只有在播放时才启动）
        QMediaContent media = mPlayList->currentMedia();
        QString filePath = media.canonicalUrl().toLocalFile();
        if (!filePath.isEmpty()) {
            // 清理之前的线程
            if (musicSendthread) {
                if (musicSendthread->isRunning()) {
                    musicSendthread->setStop(true);
                    musicSendthread->quit();
                    musicSendthread->wait();
                }
                delete musicSendthread;
            }

            // 创建并启动新线程
            musicSendthread = new MusicSendThread(filePath);
            musicSendthread->start();
        }
    }

    qDebug() << "send command: " + command;
    fuTcpServer->socket->write(command);
}

void MusicWidget::playMusicAfter(const QByteArray &ack)
{
    if(ack == "1")
    {
        //根据 isPlay 判断，播放音乐或暂停音乐，并改变按钮图标
        if(isExist)
        {
            if(!isPlay)
            {
                this->mPlayer->play();
                playButton->setIcon(QIcon(":/images/bfzn_003.png"));
                isPlay = true;
                QMessageBox::information(this,"操作成功","播放器播放成功！");
            }
            else
            {
                this->mPlayer->pause();
                playButton->setIcon(QIcon(":/images/bfzn_004.png"));
                isPlay = false;
                QMessageBox::information(this,"操作成功","播放器暂停成功！");
            }
        }
        else
            QMessageBox::critical(this,"操作失败","请添加音乐！");
    }
    else
        QMessageBox::critical(this,"操作失败","控制播放器失败！");
}

void MusicWidget::slot_prevMusic()
{
    if (fuTcpServer->socket == nullptr) {
        QMessageBox::critical(this, "错误", "客户端未连接");
        return;
    }

    // 切换歌曲时自动启动播放（如果当前在播放状态）
    if (isPlay) {
        // 先停止当前播放
        mPlayer->stop();

        // 清理之前的发送线程
        if (musicSendthread && musicSendthread->isRunning()) {
            musicSendthread->setStop(true);
            musicSendthread->quit();
            musicSendthread->wait();
            delete musicSendthread;
            musicSendthread = nullptr;
        }
    }

    QByteArray command = QByteArray::number(Common::prevMusic);
    qDebug() << "send command: " + command;
    fuTcpServer->socket->write(command);
}


void MusicWidget::prevMusicAfter(const QByteArray &ack)
{
    if(ack == "1")
    {
        this->mPlayList->previous();
        if (isPlay) {
            mPlayer->play();
        }
    }
    else
        QMessageBox::critical(this,"操作失败","控制播放器失败！");
}

void MusicWidget::slot_nextMusic()
{
    if (fuTcpServer->socket == nullptr) {
        QMessageBox::critical(this, "错误", "客户端未连接");
        return;
    }

    // 切换歌曲时自动启动播放，先停止当前播放
    mPlayer->stop();

    // 清理之前的发送线程
    if (musicSendthread && musicSendthread->isRunning()) {
        musicSendthread->setStop(true);
        musicSendthread->quit();
        musicSendthread->wait();
        delete musicSendthread;
        musicSendthread = nullptr;
    }

    QByteArray command = QByteArray::number(Common::nextMusic);
    qDebug() << "send command: " + command;
    fuTcpServer->socket->write(command);
}

void MusicWidget::nextMusicAfter(const QByteArray &ack)
{
    if(ack == "1")
    {
        this->mPlayList->next();
        if (isPlay) {
            mPlayer->play();
        }
        else
            QMessageBox::critical(this,"操作失败","控制播放器失败！");
    }
}
QList<QPair<QTime, QString>> MusicWidget::parseLrcFile(const QString &lrcFilePath) {
    //    先创建对象 QList<QPair<QTime, QString>> lyricList
    //    根据参数 lrcFilePath 用 QFile 和 QTextStream 对象读取歌词文件，循环读取文件
    //    循环内： 用每行的分、秒、毫秒组织成 QTime，歌词组织成QString
    //    用组织好的 QTime 和 QString 封装成 QPair<QTime, QString>对象
    //    放入 lyricList。最后返回 lyricList
    QList<QPair<QTime, QString>> lyricList;
    QFile file(lrcFilePath);
    if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
        return lyricList;
    }
    QTextStream in(&file);
    in.setCodec("UTF-8");
    while (!in.atEnd()) {
        QString line = in.readLine();
        if (!line.startsWith('[')) {
            continue;
        }
        QRegularExpression regex("\\[(\\d+):(\\d+)\\.(\\d+)\\](.*)");
        QRegularExpressionMatchIterator matches = regex.globalMatch(line);
        while (matches.hasNext()) {
            QRegularExpressionMatch match = matches.next();
            int minutes = match.captured(1).toInt();
            int seconds = match.captured(2).toInt();
            int milliseconds = match.captured(3).toInt();
            QString lyric = match.captured(4).trimmed();
            QTime time(0, minutes, seconds, milliseconds);
            if (!lyric.isEmpty()) {
                lyricList.append(qMakePair(time, lyric));
            }
        }
    }
    file.close();
    return lyricList;
}


void MusicWidget::loadMusicLrc(int index) {
    //    用 mPlayList 获取当前歌曲路径
    //    根据歌曲路径找到 lrc 歌词文件
    //    调用 parseLrcFile 函数获取歌词列表给 currentLrics
    //    将歌词列表 currentLrics 里的歌词循环加入到文本域 lyricsEdit 中
    currentLrics.clear();
    lyricsEdit->clear();

    // 获取当前歌曲路径
    QMediaContent media = mPlayList->media(index);
    QString musicPath = media.canonicalUrl().toLocalFile();

    if (musicPath.isEmpty()) return;

    QFileInfo musicFileInfo(musicPath);
    QString lrcPath = ":/lrc/" + musicFileInfo.completeBaseName() + ".lrc";

    qDebug() << "Loading lyrics from:" << lrcPath;

    // 解析歌词文件
    currentLrics = parseLrcFile(lrcPath);

    // 将歌词添加到文本框
    lyricsEdit->setAlignment(Qt::AlignCenter);
    for (const auto &pair : currentLrics) {
        lyricsEdit->append(QString("<center>%1</center>").arg(pair.second));
    }
}

void MusicWidget::updateLrcOfposition(qint64 position)
{
    if (currentLrics.isEmpty()) return;

    // 将毫秒转换为QTime
    QTime currentTime = QTime(0, 0, 0, 0).addMSecs(position);

    // 查找当前应显示的歌词行
    int currentLine = -1;
    for (int i = 0; i < currentLrics.size(); ++i) {
        if (currentLrics[i].first <= currentTime) {
            currentLine = i;
        } else {
            break;
        }
    }

    // 如果没有变化，直接返回
    if (currentLine == lastHighlightedLine) return;

    QTextCursor cursor(lyricsEdit->document());

    // 清除旧的高亮
    if (lastHighlightedLine >= 0) {
        cursor.movePosition(QTextCursor::Start);
        for (int i = 0; i < lastHighlightedLine; ++i) {
            cursor.movePosition(QTextCursor::Down);
        }
        cursor.select(QTextCursor::LineUnderCursor);
        QTextCharFormat defaultFormat;
        defaultFormat.setFont(lyricsEdit->currentFont());
        defaultFormat.setForeground(Qt::black);
        cursor.mergeCharFormat(defaultFormat);
        if(currentTime > currentLrics.last().first) {
            lastHighlightedLine = -1;
        }
    }

    // 设置新的高亮
    if (currentLine >= 0) {
        cursor.movePosition(QTextCursor::Start);
        for (int i = 0; i < currentLine; ++i) {
            cursor.movePosition(QTextCursor::Down);
        }
        cursor.select(QTextCursor::LineUnderCursor);
        QTextCharFormat highlightFormat;
        highlightFormat.setForeground(Qt::green);
        highlightFormat.setFontPointSize(15);
        cursor.mergeCharFormat(highlightFormat);

        // 确保歌词可见
        scrollLyricsToCenter(currentLine);
    }

    lastHighlightedLine = currentLine;
}

void MusicWidget::slot_itemDoubleClicked(QListWidgetItem *item)
{
    // 获取双击的歌曲行号
    int row = songListWidget->row(item);

    // 设置播放列表当前索引
    mPlayList->setCurrentIndex(row);
}


void MusicWidget::slot_changeSound(int value)
{
    this->soundSlider->setValue(value);
    soundSizeLabel->setText(QString("%1%").arg(value));

    // 更新音量图标
    if (value == 0) {
        soundLabel->setPixmap(QPixmap(":/images/sound0.png"));
    } else if(0 < value && value <= 30) {
        soundLabel->setPixmap(QPixmap(":/images/sound1.png"));
    } else if(30 < value && value <= 60) {
        soundLabel->setPixmap(QPixmap(":/images/sound2.png"));
    }else{
        soundLabel->setPixmap(QPixmap(":/images/sound3.png"));
    }
}
